#include "tcp_server.h"

TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
{
   // connect(this, &QTcpServer::newConnection, this, &TcpServer::newConnection);

}

TcpServer::~TcpServer()
{
    qDebug()<<"关闭tcp服务器";
    stop();
}

void TcpServer::incomingConnection(qintptr socketDescriptor)
{
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
    qRegisterMetaType<qintptr>("qintptr");

    qDebug()<<"socketDescriptor:"<<socketDescriptor;

    QTcpSocket *socket = new QTcpSocket;
    socket->setSocketDescriptor(socketDescriptor);

    //新建客户端连接
    TcpClient *client = new TcpClient(socket, socketDescriptor);

    //为每个新连接的套接字建立线程
    QThread *clientThread = new QThread();
    client->moveToThread(clientThread);
    //线程结束后，删除客户端
    connect(clientThread, &QThread::finished, client, &TcpClient::deleteLater);
    connect(clientThread,&QThread::finished, clientThread, &QThread::deleteLater);
    clientThread->start();

    //记录套接字
    m_handleTcpClientHash[socketDescriptor] = client;
    m_handleThreadHash[socketDescriptor] = clientThread;

    //关闭tcp服务器
    connect(client, &TcpClient::clientDisconnected, this, &TcpServer::disconnected);

    //传递客户端套接字发送的数据
    //connect(client, &TcpClient::sendData, this, &TcpServer::sendData);
    connect(client, static_cast<void (TcpClient::*)(const QString &, int port, const QString &)>(&TcpClient::sendData),
            this, &TcpServer::sendData);

    //转发收到的数据
    connect(client, &TcpClient::receiveData, this, &TcpServer::receiveData);

    //发送客户端成功连接的信号
    emit clientConnected(client->getIP(), client->getPort());

    // QString ip = client->getIP();
    // int port = client->getPort();
    // emit clientConnected(ip, port);
    emit sendData(client->getIP(), client->getPort(), "客户端上线");

    //连接后加入链表
    clients.append(client);

}

void TcpServer::newConnection()
{
    QTcpSocket *socket = this->nextPendingConnection(); //结束子线程

    //不加this，客户端断开连接会闪退
    TcpClient *client = new TcpClient(socket, this);

    //为每个新连接的套接字建立线程
    QThread *clientThread = new QThread;
    client->moveToThread(clientThread);
    connect(clientThread, &QThread::finished, this, &TcpClient::deleteLater);
    clientThread->start();

    //关闭tcp服务器
    connect(client, &TcpClient::clientDisconnected, this, &TcpServer::disconnected);

    //传递客户端套接字发送的数据
    //connect(client, &TcpClient::sendData, this, &TcpServer::sendData);
    connect(client, static_cast<void (TcpClient::*)(const QString &, int port, const QString &)>(&TcpClient::sendData),
            this, &TcpServer::sendData);

    //转发收到的数据
    connect(client, &TcpClient::receiveData, this, &TcpServer::receiveData);

    //发送客户端成功连接的信号
    emit clientConnected(client->getIP(), client->getPort());

    emit sendData(client->getIP(), client->getPort(), "客户端上线");

    //连接后加入链表
    clients.append(client);
}

void TcpServer::disconnected(qintptr socketDescriptor)
{
    qDebug()<<"main currentThreadId()"<<this->thread()->currentThreadId();

    qDebug()<<"server currentThreadId()"<<m_handleThreadHash[socketDescriptor]->currentThreadId();

    qDebug()<<"socket currentThreadId()"<<m_handleTcpClientHash[socketDescriptor]->thread()->currentThreadId();

    qDebug()<<"客户端下线";
    TcpClient *client = (TcpClient *)sender();
    QString ip = client->getIP();
    int port = client->getPort();
    qDebug()<<"客户端下线的信息"<<ip<<" "<<port;

    emit clientDisconnected(ip, port);
    emit sendData(ip, port, "客户端下线");

    //断开连接后从链表中移除
    clients.removeOne(client);

    // client->m_socket->deleteLater();
    // client->deleteLater();

    //下面的代码会让客户端断开连接后，会退出
    // qDebug()<<"socketDescriptor:"<<socketDescriptor;
    m_handleThreadHash[socketDescriptor]->quit();
    m_handleThreadHash[socketDescriptor]->wait();
    m_handleThreadHash.remove(socketDescriptor);
    m_handleTcpClientHash.remove(socketDescriptor);

}

bool TcpServer::start(QString ip, int port)
{
    bool ok = listen(QHostAddress(ip), port);
    return ok;
}

void TcpServer::stop()
{
    remove();
    this->close();
}

void TcpServer::writeData(const QString &ip, int port, const QString &data)
{
    foreach (TcpClient *client, clients) {
        if (client->getIP() == ip && client->getPort() == port) {
            client->sendData(data);
            break;
        }
    }
}

void TcpServer::writeData(const QString &data)
{
    foreach (TcpClient *client, clients) {
        client->sendData(data);
    }
}

void TcpServer::remove(const QString &ip, int port)
{
    foreach (TcpClient *client, clients) {
        if (client->getIP() == ip && client->getPort() == port) {
            client->abort();
            break;
        }
    }
}

void TcpServer::remove()
{
    foreach (TcpClient *client, clients) {
        client->abort();
    }
}
